package com.bicntech.system.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import com.bicntech.common.exception.ServiceException;
import com.bicntech.common.utils.file.ImgUtils;
import com.bicntech.system.service.FileService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.regex.Pattern;

/**
 * @author : JMY
 * @create 2023/8/21 9:43
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class FileServiceImpl implements FileService {

    @Value("${image.path}")
    private String filePath;

    /**
     * The Snowflake
     */
    private final Snowflake snowflake = new Snowflake();

    /**
     * 定义要过滤的特殊符号
     */
    private static final String REGEX =
            "[\\u00A0\\s\"`~!@#$%^&*()+=|{}':;',\\[\\]<>/?~！@#￥%……&*（）+|{}【】‘；：”“’。，、？]";

    /**
     * 过滤正则
     */
    private static final Pattern FILTER_PATTERN = Pattern.compile(REGEX);

    @Override
    public String uploadFile(MultipartFile file) {

        // 效验 MultipartFile 是否为图片
        if (!ImgUtils.isImage(file)) throw new ServiceException("请上传图片文件！");
        try {
            String fileName = this.processName(file.getOriginalFilename(), Boolean.TRUE);
            FileUtils.copyToFile(file.getInputStream(), new File(filePath + fileName));
            return fileName;
        } catch (IOException e) {
            throw new ServiceException("上传失败！");
        }
    }

    @Override
    public Boolean deleteExpire(Integer validationDays) {
        String localDate = LocalDate.now().minusDays(validationDays).toString();
        return FileUtil.del(filePath + localDate);
    }

    /**
     * Process name string.
     *
     * @param objectName the object name
     * @return the string
     */
    @VisibleForTesting
    public String processName(String objectName, Boolean isSplicingDate) {
        objectName = filterSpecialSymbols(objectName).replaceAll("\\s*", "");
        String n = getPathFileName(isSplicingDate, objectName);
        do {
            if (!checkFileIsExist(n)) {
                return n;
            }
            n = FilenameUtils.getBaseName(objectName);
        } while (checkFileIsExist((n = n + "_" + snowflake.nextId())));

        String joinUrl = n + "." + FileNameUtil.extName(objectName);

        joinUrl = getPathFileName(isSplicingDate, joinUrl);
        return joinUrl;
    }

    /**
     * 过滤文件名中的特殊符号
     *
     * @param objectName 文件名称
     * @return 过滤后的文件名
     */
    public String filterSpecialSymbols(String objectName) {
        objectName = FILTER_PATTERN.matcher(objectName).replaceAll("").trim();
        return objectName;
    }

    /**
     * 获取文件完整路径名称
     *
     * @param isSplicingDate
     * @param name
     * @return
     */
    private String getPathFileName(Boolean isSplicingDate, String name) {
        if (ObjectUtil.isEmpty(isSplicingDate) || isSplicingDate) {
            name = Joiner.on("/").join(LocalDate.now(), name);
        }
        return name;
    }

    /**
     * Check file is exist boolean.
     *
     * @param objectName the object name
     * @return the boolean
     */
    public Boolean checkFileIsExist(String objectName) {
        return FileUtil.exist(filePath + objectName);
    }

}
